#pragma once
#include<string>
#include<unordered_map>
#include"../HttpRequest/HttpRequest.hpp"
#include"../Util/Util.hpp"
#include"../../Server/TcpServer/TcpServer.hpp"

//这个模块是对从Buffer获取的http的请求做解析以及存储到一个HttpRequest中，以便服务器进行处理
//要素：
//响应状态，请求的处理状态(处理请求行，处理请求头部，处理请求正文，处理错误，处理完成)，解析后的请求(HttpRequest)
//功能：
//获取并解析http请求(对请求行解析->对请求头部解析->对请求正文解析)
//获取响应状态
//获取请求的处理状态
//获取解析后的请求
//重置

#define MAX_LINE 8192
typedef enum{
    //请求的处理状态
    request_line,
    request_head,
    request_body,
    request_error,
    request_over
}RequestStatus;

class HttpContext{
private:
    int _response_status;//响应状态
    RequestStatus _request_status;//请求处理状态
    HttpRequest _request;//解析后的请求
private:
    //请求行解析函数，设置_request的请求行内容
    bool request_line_prased(std::string& line)
    {
        std::smatch match;
        std::regex rgx("(GET|HEAD|POST|PUT|DELETE) ([^?]*)(?:\\?(.*))? (HTTP/1\\.[01])(?:\n|\r\n)?", std::regex::icase);
        bool ret = std::regex_match(line, match, rgx);
        if(ret == false)
        {
            _response_status = 400;//BAD REQUEST
            _request_status = request_error;
            return false;
        }
        //将数据设置到_request
            //设置请求方法,并将其内容设置为大写
        _request._method = match[1];
        std::transform(_request._method.begin(), _request._method.end(), _request._method.begin(), ::toupper);
            //设置请求资源路径，并进行解码，但是不需要+转空格
        _request._path = Util::URLDecode(match[2], false);
            //设置版本协议
        _request._vision = match[4];
            //设置查询字符串，先按照&进行分割，然后对每个字符串按照=分割，对每个值进行解码，并且+要转化为空格
        std::vector<std::string> array;
        Util::split(match[3], "&", array);
        for(auto& e:array)
        {
            int pos = e.find("=");
            if(pos == std::string::npos)
            {
                ERR_LOG("错误-查询字符串");
                _response_status = 400;//BAD REQUEST
                _request_status = request_error;
                return false;
            }
            std::string key = Util::URLDecode(e.substr(0, pos), true);
            std::string val = Util::URLDecode(e.substr(pos+1), true);
            _request.SetParams(key, val);
        }
        return true;
    }
    //请求行处理函数，获取的请求行后内部调用请求行解析
    bool recv_http_request_line(Buffer& buf)
    {
        //检查请求处理状态
        if(_request_status != request_line)
            return false;

        //获取请求行
            //从Buffer中获取一行数据
        std::string line = buf.line_read();
        
        if(line.size() == 0)
        {
            //读到的是空的,但是缓冲区的数据超大，就出错了
            if(buf.get_readable_size() > MAX_LINE)
            {
                _response_status = 414;//URI TOO LONG
                _request_status = request_error;
                return false;
            }
            //读到的是空的,缓冲区的数据也不多，就等新数据到来
            return true;
        }
        if(line.size() > MAX_LINE)
        {
            //数据超大，出错
            _response_status = 414;//URI TOO LONG
            _request_status = request_error;
            return false;
        }

        //获取到请求行，调用请求行解析函数对其进行解析
        int ret = request_line_prased(line);
        if(ret == false)
        {
            return false;
        }
        else
        {
            //修改请求处理状态，处理请求头部
            _request_status = request_head;
            return true;
        }
    }

    //请求头部解析函数，设置_request的请求行内容
    bool request_head_prased(std::string& line)
    {
        //末尾是\n或者\r\n要删除
        // if(line.back() == '\n')     line.pop_back();
        // if(line.back() == '\r')     line.pop_back();

        // int pos = line.find(": ");
        // if(pos == std::string::npos)
        // {
        //     ERR_LOG("错误-头部");
        //     _response_status = 400;//BAD REQUEST
        //     _request_status = request_error;
        //     return false;
        // }
        // std::string key = line.substr(0, pos);
        // std::string val = line.substr(pos+2);
        // _request.SetHeader(key, val);
        // return true;
        if (line.back() == '\n') line.pop_back();//末尾是换行则去掉换行字符
            if (line.back() == '\r') line.pop_back();//末尾是回车则去掉回车字符
            size_t pos = line.find(": ");
            if (pos == std::string::npos) {
                _response_status = 400;//BAD REQUEST
                _request_status = request_error;
                return false;
            }
            std::string key = line.substr(0, pos);  
            std::string val = line.substr(pos + 2);
            _request.SetHeader(key, val);
            return true;
    }
    //请求头部处理函数，获取的请求头部后内部调用请求头部解析
    bool recv_http_head(Buffer& buf)
    {
        //检查处理请求状态
        if(_request_status != request_head)     {return false;}

        //循环读取，直到读取到空行
        while(1)
        {
            std::string line = buf.line_read();
            if(line.size() == 0)
            {
                //读到的是空的,但是缓冲区的数据超大，就出错了
                if(buf.get_readable_size() > MAX_LINE)
                {
                    ERR_LOG("URI TOO LONG");
                    _response_status = 414;//URI TOO LONG
                    _request_status = request_error;
                    return false;
                }
                //读到的是空的,缓冲区的数据也不多，就等新数据到来
                return true;
            }
            if(line.size() > MAX_LINE)
            {
                //数据超大，出错
                _response_status = 414;//URI TOO LONG
                _request_status = request_error;
                return false;
            }
            if (line == "\n" || line == "\r\n") 
            {
                    break;
            }
            //获取到请求行，调用请求行解析函数对其进行解析
            int ret = request_head_prased(line);
            if(ret == false)
            {
                return false;
            }
        }
        //修改请求处理状态，处理请求正文
        _request_status = request_body;
        return true;
    }

    bool recv_http_body(Buffer& buf)
    {
        //检查请求处理状态
        if(_request_status != request_body)
            return false;

        //获取请求正文大小
        int length = _request.ContentLength();
        if(length == 0)
        {
            //没有正文，接收完毕
            _request_status = request_over;
            return true;
        }

        //计算还有多少正文没有读
        int remain = length - _request._body.size();

        if(buf.get_readable_size() < remain)
        {
            //数据还没有全部送到，把现有的数据取过来，不改变请求处理状态
            _request._body.append(buf.get_read_ptr(), buf.get_readable_size());
            buf.move_read_pos(buf.get_readable_size());
            return true;
        }
        else
        {
            _request._body.append(buf.get_read_ptr(), remain);
            buf.move_read_pos(remain);
            _request_status = request_over;
            return true;
        }
        
    }
public:
    HttpContext()
    :_response_status(200)
    ,_request_status(request_line)
    {}

    //获取并解析http请求(对请求行解析->对请求头部解析->对请求正文解析)
    void RecvHttpRequest(Buffer& buf)
    {
        switch (_request_status)
        {
        case request_line:
            //调用请求行处理函数，调用后不需要break，直接处理请求头部
            recv_http_request_line(buf);
        case request_head:
            //调用请求头部处理函数，调用后不需要break，直接处理请求正文
            recv_http_head(buf);
        case request_body:
            //调用请求正文处理函数
            recv_http_body(buf);
        }
        return;
    }

    //获取响应状态
    int GetResponseStatus()     {return _response_status;}
    //获取请求的处理状态
    RequestStatus GetRequestStatus()    {return _request_status;}
    //获取解析后的请求
    HttpRequest& GetRequest()   {return _request;}
    //重置
    void Reset()
    {
        _response_status = 200;
        _request_status = request_line;
        _request.Reset();
    }
};